/**
 * @file CommunicationService.cpp
 * @brief 通信服务类实现
 * @author Your Name
 * @date 2025-03-30
 */

#include "communicationservice.h"
#include <QDebug>
#include <QDataStream>
// #include <QDataTime>

CommunicationService::CommunicationService(QObject *parent)
    : QObject(parent), m_running(false) {

    // 设置心跳包定时器
    m_heartbeatTimer.setInterval(3000); // 3秒一次心跳
    connect(&m_heartbeatTimer, &QTimer::timeout, this, &CommunicationService::sendHeartbeat);
}

CommunicationService::~CommunicationService() {
    stop();
}

bool CommunicationService::init(ICommunicationStrategy* commStrategy, IProtocol* protocol) {
    // 参数检查
    if (!commStrategy || !protocol) {
        qWarning() << "通信服务初始化失败: 无效的通信策略或协议对象";
        return false;
    }

    // 关闭当前服务
    stop();

    // 设置新的通信策略和协议
    m_commStrategy.reset(commStrategy);
    m_protocol.reset(protocol);

    // 连接信号
    connect(m_commStrategy.data(), &ICommunicationStrategy::dataReceived,
            this, &CommunicationService::onDataReceived);
    connect(m_commStrategy.data(), &ICommunicationStrategy::connectionChanged,
            this, &CommunicationService::onConnectionChanged);
    connect(m_commStrategy.data(), &ICommunicationStrategy::errorOccurred,
            this, &CommunicationService::onCommunicationError);

    connect(m_protocol.data(), &IProtocol::packetParsed,
            this, &CommunicationService::onPacketParsed);
    connect(m_protocol.data(), &IProtocol::protocolError,
            this, &CommunicationService::onProtocolError);

    qInfo() << "通信服务初始化完成";
    return true;
}

bool CommunicationService::start() {
    // 检查是否已初始化
    if (!m_commStrategy || !m_protocol) {
        qWarning() << "通信服务启动失败: 未初始化";
        emit serviceError(-1, "通信服务未初始化");
        return false;
    }

    // 如果已经运行，先停止
    if (m_running) {
        stop();
    }

    // 尝试打开通信连接
    bool success = m_commStrategy->open();

    if (success) {
        m_running = true;
        qInfo() << "通信服务启动成功";

        // 启动心跳定时器
        m_heartbeatTimer.start();

        // 更新最后接收时间
        m_lastReceivedTime = QDateTime::currentDateTime();
    } else {
        qWarning() << "通信服务启动失败: 无法打开通信连接";
        emit serviceError(-2, "无法打开通信连接");
    }

    return success;
}

void CommunicationService::stop() {
    // 停止心跳定时器
    m_heartbeatTimer.stop();

    // 关闭通信连接
    if (m_commStrategy) {
        m_commStrategy->close();
    }

    m_running = false;
    qInfo() << "通信服务已停止";
}

bool CommunicationService::isRunning() const {
    return m_running && m_commStrategy && m_commStrategy->isConnected();
}

bool CommunicationService::sendDeviceControl(uint8_t controlBits) {
    // 控制位作为单字节数据
    QByteArray data;
    data.append(static_cast<char>(controlBits));

    // 发送控制命令
    bool success = sendPacket(Protocol::CMD_DEVICE_CONTROL, data);

    if (success) {
        qInfo() << "发送设备控制命令成功, 控制位:" << QString::number(controlBits, 16);
    }

    return success;
}

bool CommunicationService::sendTimeSync(uint32_t timestamp) {
    // 如果未指定时间戳，使用当前时间
    if (timestamp == 0) {
        timestamp = QDateTime::currentDateTime().toSecsSinceEpoch();
    }

    // 将时间戳转换为大端序字节数组
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::BigEndian);
    stream << timestamp;

    // 发送时间同步命令
    bool success = sendPacket(Protocol::CMD_TIME_SYNC, data);

    if (success) {
        qInfo() << "发送时间同步命令成功, 时间戳:" << timestamp;
    }

    return success;
}

void CommunicationService::onDataReceived(const QByteArray& data) {
    // 更新最后接收时间
    m_lastReceivedTime = QDateTime::currentDateTime();

    // 将数据交给协议解析器处理
    m_protocol->parseReceivedData(data);
}

void CommunicationService::onPacketParsed(uint8_t cmdType, const QByteArray& data) {
    // 根据命令类型分别处理
    switch (cmdType) {
        case Protocol::CMD_ENV_DATA:
            parseEnvironmentData(data); // 环境状态数据
            break;

        case Protocol::CMD_RFID_REPORT: // 考勤上报数据
            parseRfidReport(data);
            break;

        case Protocol::CMD_HEARTBEAT:   // 心态包数据
            parseHeartbeat(data);
            break;

        case Protocol::CMD_ERROR_RESP:  // 错误应答
            parseErrorResponse(data);
            break;

        default:
            qWarning() << "收到未知命令类型:" << QString::number(cmdType, 16);
            break;
    }
}

void CommunicationService::onProtocolError(int errCode, const QString& errMsg) {
    qWarning() << "协议错误:" << errCode << errMsg;
    emit serviceError(errCode, "协议错误: " + errMsg);
}

void CommunicationService::onCommunicationError(int code, const QString& message) {
    qWarning() << "通信错误:" << code << message;
    emit serviceError(code, "通信错误: " + message);
}

void CommunicationService::onConnectionChanged(bool connected) {
    qInfo() << "通信连接状态变化:" << (connected ? "已连接" : "已断开");
    emit connectionStatusChanged(connected);

    // 连接状态变化时处理心跳定时器
    if (connected && m_running) {
        if (!m_heartbeatTimer.isActive()) {
            m_heartbeatTimer.start();
        }
    } else {
        if (m_heartbeatTimer.isActive()) {
            m_heartbeatTimer.stop();
        }
    }
}

void CommunicationService::parseEnvironmentData(const QByteArray& data) {
    // 检查数据长度
    if (data.size() < 5) {
        qWarning() << "环境数据格式错误: 数据长度不足";
        return;
    }

    // 解析温度数据 (2字节，0.1℃精度)
    QDataStream stream(data);
    stream.setByteOrder(QDataStream::BigEndian);

    uint16_t tempRaw;
    uint8_t humidity;
    uint16_t battery;

    stream >> tempRaw >> humidity >> battery;

    // 转换为实际温度值
    float temperature = tempRaw / 10.0f;

    qInfo() << "收到环境数据: 温度=" << temperature << "℃, 湿度=" << humidity
            << "%, 电量=" << battery;

    // 发送信号
    emit environmentDataReceived(temperature, humidity, battery);
}

void CommunicationService::parseRfidReport(const QByteArray& data) {
    // 检查数据长度
    if (data.size() < 9 - 4 - 1) {
        qWarning() << "RFID报告格式错误: 数据长度不足";
        return;
    }
#if 0
    // // BCD编码的卡号转换为uint32
    // uint32_t cardId = 0;
    // for (int i = 0; i < 4; i++) {
    //     uint8_t byte = static_cast<uint8_t>(data.at(i));
    //     uint8_t high = (byte >> 4) & 0x0F;
    //     uint8_t low = byte & 0x0F;

    //     cardId = cardId * 10 + high;
    //     cardId = cardId * 10 + low;
    // }
#else
    QString cardIdStr;
    for (int i = 0; i < 4; ++i) {
        uint8_t byte = static_cast<uint8_t>(data.at(i));

        // 将每个半字节转换为十六进制字符
        char high = (byte >> 4) & 0x0F;
        char low = byte & 0x0F;

        // 数字转字符处理（0x7 -> '7'，0xA -> 'A'）
        high = (high < 10) ? ('0' + high) : ('A' + (high - 10));
        low = (low < 10) ? ('0' + low) : ('A' + (low - 10));

        cardIdStr.append(high).append(low);
    }
#endif
    // 解析时间戳和状态码
    // QByteArray timestampBytes = data.mid(4, 4);
    // QDataStream stream(timestampBytes);
    // stream.setByteOrder(QDataStream::BigEndian);

    uint32_t timestamp = QDateTime::currentDateTime().toSecsSinceEpoch();
    // stream >> timestamp;

    uint8_t statusCode = 0x01;// static_cast<uint8_t>(data.at(8 - 4));

    qInfo() << "收到RFID报告: 卡号=" << cardIdStr
            << ", 时间戳=" << QDateTime::fromSecsSinceEpoch(timestamp).toString("yyyy-MM-dd hh:mm:ss")
            << ", 状态码=" << QString::number(statusCode, 16);

    // 发送信号
    emit rfidReportReceived(cardIdStr, timestamp, statusCode);
}

void CommunicationService::parseHeartbeat(const QByteArray& data) {
    // 检查数据长度
    if (data.size() < 2) {
        qWarning() << "心跳包格式错误: 数据长度不足";
        return;
    }

    // 解析电压和信号强度
    uint8_t voltageRaw = static_cast<uint8_t>(data.at(0));
    uint8_t signalStrength = static_cast<uint8_t>(data.at(1));

    // 转换为实际电压值
    float voltage = voltageRaw / 10.0f;

    qDebug() << "收到心跳包: 电压=" << voltage << "V, 信号强度=" << signalStrength;

    // 发送信号
    emit heartbeatReceived(voltage, signalStrength);
}

void CommunicationService::parseErrorResponse(const QByteArray& data) {
    // 检查数据长度
    if (data.isEmpty()) {
        qWarning() << "错误应答格式错误: 数据长度不足";
        return;
    }

    // 解析错误码
    uint8_t errorCode = static_cast<uint8_t>(data.at(0));

    QString errorMsg = "收到错误应答: ";
    switch (errorCode) {
        case Protocol::ERR_CHECKSUM:
            errorMsg += "校验错误";
            break;
        case Protocol::ERR_LENGTH:
            errorMsg += "长度不符";
            break;
        case Protocol::ERR_COMMAND:
            errorMsg += "命令不支持";
            break;
        case Protocol::ERR_TIMEOUT:
            errorMsg += "通信超时";
            break;
        case Protocol::ERR_PARAM:
            errorMsg += "参数错误";
            break;
        default:
            errorMsg += "未知错误代码: " + QString::number(errorCode);
            break;
    }

    qWarning() << errorMsg;

    // 发送信号
    emit errorResponseReceived(errorCode);
}

bool CommunicationService::sendPacket(uint8_t cmdType, const QByteArray& data) {
    // 检查服务是否运行
    if (!isRunning()) {
        qWarning() << "发送数据失败: 服务未运行或未连接";
        return false;
    }

    // 使用协议编码数据包
    QByteArray packet = m_protocol->encodePacket(cmdType, data);

    if (packet.isEmpty()) {
        qWarning() << "发送数据失败: 数据包编码错误";
        return false;
    }

    // 发送数据包
    qint64 bytesSent = m_commStrategy->send(packet);

    return bytesSent == packet.size();
}

void CommunicationService::sendHeartbeat() {
    if (!isRunning()) {
        return;
    }

    // 简单的心跳包，只发命令而不带数据
    sendPacket(Protocol::CMD_HEARTBEAT, QByteArray());
}
